home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 24
/
Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso
/
Aminet
/
comm
/
mail
/
Mutt089src.lha
/
Mutt-0.89i-AMIGA
/
src
/
mbox.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-01-28
|
24KB
|
992 lines
/*
* Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* This file contains code to parse ``mbox'' and ``mmdf'' style mailboxes */
#include "mutt.h"
#include "mailbox.h"
#include "mx.h"
#include "sort.h"
#include "parse.h"
#include "copy.h"
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <utime.h>
#include <sys/file.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
/* struct used by mutt_sync_mailbox() to store new offsets */
struct m_update_t
{
long hdr;
long body;
};
#ifdef USE_DOTLOCK
/*
* Determine whether or not to use a dotlock to lock the indicated file.
* On some systems, the spool directory is not world-writable. If it is
* group-writable, we might need to be setgid() to write the lock. If not
* group-writable, then we assume that fcntl() locking is enough and skip
* the dotlocking.
*
* return values:
* 2 need to be setgid to dotlock
* 1 can use a dotlock
* 0 don't use a dotlock
* -1 error
*/
static int can_dotlock (const char *path)
{
char tmp[_POSIX_PATH_MAX];
char *p;
#ifdef USE_SETGID
struct stat sb;
#endif
strfcpy (tmp, path, sizeof (tmp));
if ((p = strrchr (tmp, '/')))
*p = 0;
else
strfcpy (tmp, ".", sizeof (tmp)); /* use current directory */
if (access (tmp, W_OK) == 0) return 1;
#ifdef USE_SETGID
if (stat (tmp, &sb) == 0)
{
if ((sb.st_mode & S_IWGRP) == S_IWGRP)
{
/* can dotlock, but need to be setgid */
if (sb.st_gid == MailGid)
return (2);
else
{
mutt_error ("Need to be running setgid %d to lock mailbox!", sb.st_gid);
return (-1);
}
}
}
#endif
if (mutt_yesorno ("Can't dotlock mailbox, continue anyway?", 0) == 1)
return 0;
return (-1);
}
#endif
int mbox_lock_mailbox (CONTEXT *ctx, int excl)
{
int r = 0;
#ifdef USE_DOTLOCK
r = can_dotlock (ctx->path);
if (r == -1)
return (-1);
#ifdef USE_SETGID
else if (r == 2)
{
/* need to be setgid to lock the mailbox */
if (SETEGID (MailGid) != 0)
{
mutt_perror ("setegid");
return (-1);
}
ctx->setgid = 1;
}
#endif /* USE_SETGID */
#endif /* USE_DOTLOCK */
if ((r = mx_lock_file (ctx->path, fileno (ctx->fp), excl, r)) == 0)
ctx->locked = 1;
#ifdef USE_SETGID
if (ctx->setgid)
SETEGID (UserGid);
#endif
return (r);
}
void mbox_unlock_mailbox (CONTEXT *ctx)
{
if (ctx->locked)
{
fflush (ctx->fp);
#ifdef USE_SETGID
if (ctx->setgid)
SETEGID (MailGid);
#endif /* USE_SETGID */
mx_unlock_file (ctx->path, fileno (ctx->fp));
ctx->locked = 0;
#ifdef USE_SETGID
if (ctx->setgid)
{
SETEGID (UserGid);
ctx->setgid = 0;
}
#endif
}
}
int mmdf_parse_mailbox (CONTEXT *ctx)
{
char buf[HUGE_STRING];
char return_path[LONG_STRING];
int lines;
time_t t;
long loc, tmploc;
HEADER *hdr;
struct stat sb;
#ifdef NFS_ATTRIBUTE_HACK
struct utimbuf newtime;
#endif
if (stat (ctx->path, &sb) == -1)
{
mutt_perror (ctx->path);
return (-1);
}
ctx->mtime = sb.st_mtime;
ctx->size = sb.st_size;
#ifdef NFS_ATTRIBUTE_HACK
if (sb.st_mtime > sb.st_atime)
{
newtime.modtime = sb.st_mtime;
newtime.actime = time (NULL);
utime (ctx->path, &newtime);
}
#endif
buf[sizeof (buf) - 1] = 0;
FOREVER
{
if (fgets (buf, sizeof (buf) - 1, ctx->fp) == NULL)
break;
if (strcmp (buf, MMDF_SEP) == 0)
{
loc = ftell (ctx->fp);
if (ctx->msgcount == ctx->hdrmax)
mx_alloc_memory (ctx);
ctx->hdrs[ctx->msgcount] = hdr = mutt_new_header ();
hdr->offset = loc;
hdr->index = ctx->msgcount;
if (fgets (buf, sizeof (buf) - 1, ctx->fp) == NULL)
{
dprint (1, (debugfile, "mmdf_parse_mailbox: unexpected EOF\n"));
break;
}
return_path[0] = 0;
t = is_from (buf, return_path, sizeof (return_path));
if (!t)
fseek (ctx->fp, loc, 0);
else
hdr->received = t;
hdr->env = mutt_read_rfc822_header (ctx->fp, hdr);
loc = ftell (ctx->fp);
if (hdr->content->length > 0 && hdr->lines > 0)
{
tmploc = loc + hdr->content->length;
if (tmploc < ctx->size)
{
fseek (ctx->fp, tmploc, 0);
if (fgets (buf, sizeof (buf) - 1, ctx->fp) == NULL ||
strcmp (MMDF_SEP, buf) != 0)
{
fseek (ctx->fp, loc, 0);
hdr->content->length = -1;
}
}
else
hdr->content->length = -1;
}
else
hdr->content->length = -1;
if (hdr->content->length < 0)
{
lines = -1;
do {
loc = ftell (ctx->fp);
if (fgets (buf, sizeof (buf) - 1, ctx->fp) == NULL)
break;
lines++;
} while (strcmp (buf, MMDF_SEP) != 0);
hdr->lines = lines;
hdr->content->length = loc - hdr->content->offset;
}
if (!hdr->env->return_path && return_path[0])
rfc822_parse_adrlist (&hdr->env->return_path, return_path, "@");
if (!hdr->env->from)
hdr->env->from = rfc822_cpy_adr (hdr->env->return_path);
mx_update_context (ctx);
}
else
{
dprint (1, (debugfile, "mmdf_parse_mailbox: corrupt mailbox!\n"));
mutt_error ("Mailbox is corrupt!");
return (-1);
}
}
return 0;
}
/* Note that this function is also called when new mail is appended to the
* currently open folder, and NOT just when the mailbox is initially read.
*
* NOTE: it is assumed that the mailbox being read has been locked before
* this routine gets called. Strange things could happen if it's not!
*/
int mbox_parse_mailbox (CONTEXT *ctx)
{
struct stat sb;
char buf[HUGE_STRING], return_path[STRING];
HEADER *curhdr;
time_t t;
int count = 0, lines = 0;
long loc;
#ifdef NFS_ATTRIBUTE_HACK
struct utimbuf newtime;
#endif
/* Save information about the folder at the time we opened it. */
if (stat (ctx->path, &sb) == -1)
{
mutt_perror (ctx->path);
return (-1);
}
ctx->size = sb.st_size;
ctx->mtime = sb.st_mtime;
#ifdef NFS_ATTRIBUTE_HACK
if (sb.st_mtime > sb.st_atime)
{
newtime.modtime = sb.st_mtime;
newtime.actime = time (NULL);
utime (ctx->path, &newtime);
}
#endif
if (!ctx->readonly)
ctx->readonly = access (ctx->path, W_OK) ? 1 : 0;
loc = ftell (ctx->fp);
while (fgets (buf, LONG_STRING, ctx->fp) != NULL)
{
if ((t = is_from (buf, return_path, sizeof (return_path))))
{
/* Save the Content-Length of the previous message */
if (count > 0)
{
#define PREV ctx->hdrs[ctx->msgcount-1]
if (PREV->content->length < 0)
{
PREV->content->length = loc - PREV->content->offset - 1;
if (PREV->content->length < 0)
PREV->content->length = 0;
}
if (!PREV->lines)
PREV->lines = lines ? lines - 1 : 0;
}
count++;
if (!ctx->quiet && ReadInc && ((count % ReadInc == 0) || count == 1))
mutt_message ("Reading %s... %d (%d%%)", ctx->path, count,
ftell (ctx->fp) / (ctx->size / 100 + 1));
if (ctx->msgcount == ctx->hdrmax)
mx_alloc_memory (ctx);
curhdr = ctx->hdrs[ctx->msgcount] = mutt_new_header ();
curhdr->received = t;
curhdr->offset = loc;
curhdr->index = ctx->msgcount;
curhdr->env = mutt_read_rfc822_header (ctx->fp, curhdr);
/* if we know how long this message is, either just skip over the body,
* or if we don't know how many lines there are, count them now (this will
* save time by not having to search for the next message marker).
*/
if (curhdr->content->length > 0)
{
long tmploc;